package il.technion.cs236369.webserver.components;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import javax.net.ServerSocketFactory;

import org.apache.http.HttpServerConnection;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;

/**
 * The class implements the interface IConnectionListener.
 * @author Ofir Haviv and Itamar Talmi
 *
 */
public class ConnectionListener implements IConnectionListener {

	private ServerSocket serverSocket;
	private BlockingQueue<HttpServerConnection> socketQueue;
	private HttpParams params;
	
	public ConnectionListener(ServerSocketFactory srvSockFactory,
			int bindingPort,
			int socketQueueCapacity,
			int numberOfSocketReadersThreads,
			IDataHandler<HttpServerConnection> socketHandler) throws IOException{
		serverSocket = srvSockFactory.createServerSocket(bindingPort);
		socketQueue = new LinkedBlockingQueue<HttpServerConnection>(socketQueueCapacity);
		new QueueHandler<HttpServerConnection>(numberOfSocketReadersThreads, socketQueue, socketHandler);
		
        params = new SyncBasicHttpParams();
        params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false);
        params.setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true);
	}

	@Override
	public void start() {
		
		while (true){
			try {
				System.out.println("listining on port " + serverSocket.getLocalPort());
				Socket connectionSocket = serverSocket.accept();
				DefaultHttpServerConnection connection = new DefaultHttpServerConnection(); 
                connection.bind(connectionSocket, params);
				if (socketQueue.offer(connection) == false){
					// response with code 503 (PDF page 6 in the "The Main Server Class" section).	                
	                ServerUtils.sendInternalServerError(connection);
					
					System.err.println("Can't insert new socket to the queue");
				}
				
			} catch (IOException e) {
				System.err.println("Error in ConnectionListener.start");
				e.printStackTrace();
			}
		}
		
	}
}
